import { IMGPosition } from "@/pages/entry/handelImage";
import { hexToRGBA } from "./colorTool";
import { cloneDeep } from "lodash";
//import worker_setColor from "@/worker/setColor";
interface SETCOLOR {
  x: number;
  y: number;
  size: { width: number; height: number };
  colors: Uint8ClampedArray;
  repleceColor: number[]; //初始被替换的色值
  targetColor: string; //目标色值
  precision: number; //精度值
}
export interface REPLACECOLOR {
  x: number;
  y: number;
  canvas: HTMLCanvasElement;
  targetColor: string; // 目标色值
  precision?: number; // 视为相同类型色值相似度
  format?: string; //导出格式
  imgPosition?: IMGPosition; //图片的位置不能把整个的canvas导出图片
}
export const getNewCanvas = (
  ctx: CanvasRenderingContext2D,
  imgPosition: IMGPosition
): HTMLCanvasElement => {
  //获取图片区域的ctx
  const { imgX, imgY, imgWidth, imgHeight } = imgPosition as IMGPosition;
  const imgData = ctx.getImageData(imgX, imgY, imgWidth, imgHeight);

  // 把图片的imgData放置在和图片一样大小的新canvas中
  const newCanvas = document.createElement("canvas");
  newCanvas.width = imgWidth;
  newCanvas.height = imgHeight;
  const newCtx = newCanvas.getContext("2d") as CanvasRenderingContext2D;
  newCtx.putImageData(imgData, 0, 0);
  return newCanvas;
};
//判断一个的差距
const compareColor = (numA: number, numB: number, precision: number) => {
  return Math.abs(numA - numB) < precision;
};
//拿到点击像素的getImageData下标
const point2Index = (x: number, y: number, canvasWidth: number) =>
  (y * canvasWidth + x) * 4;
//判断批量替换色值的差距
const isDiff = (
  startColor: number[], //初始要求替换的色值
  nextColor: number[], //影响周边范围色值
  precision: number
) => {
  const res =
    compareColor(startColor[0], nextColor[0], precision) &&
    compareColor(startColor[1], nextColor[1], precision) &&
    compareColor(startColor[2], nextColor[2], precision) &&
    compareColor(startColor[3], nextColor[3], precision);
  return !res;
};
//设置要替换的颜色
const setColor = ({
  x,
  y,
  size,
  colors,
  repleceColor,
  targetColor,
  precision,
}: SETCOLOR): boolean => {
  const { r, g, b, a } = hexToRGBA(targetColor);
  const i = point2Index(x, y, size.width);
  const thisColor: number[] = [
    colors[i],
    colors[i + 1],
    colors[i + 2],
    colors[i + 3],
  ];
  if (x < 0 || x >= size.width || x < 0 || y >= size.height) {
    console.log("超出范围");
    return false;
  }
  const isSame =
    JSON.stringify(thisColor) ===
    JSON.stringify([r, g, b, Math.round(a * 255)]);
  //当前替换色已经和目标色值一样
  if (isSame) {
    console.log("当前替换色已经和目标色值一样");
    return false;
  }
  const isReplace = isDiff(repleceColor, thisColor, precision);
  // 初始替换色和要被替换的色相差不能超过precision
  if (isReplace) {
    console.log("超过precision");
    return false;
  }

  colors[i] = r;
  colors[i + 1] = g;
  colors[i + 2] = b;
  colors[i + 3] = Math.round(a * 255);
  return true;
};

const repleceColor = (props: REPLACECOLOR): Promise<string> => {
  return new Promise((resolve, _reject) => {
    const {
      x,
      y,
      canvas,
      targetColor,
      precision = 10,
      format = "png",
      imgPosition,
    } = props;
    const i = point2Index(x, y, canvas.width);
    const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
    const imageData: ImageData = ctx.getImageData(
      0,
      0,
      canvas.width,
      canvas.height
    );
    const colors = imageData.data;
    // 初始被替换的色值
    const repleceColor = cloneDeep([
      colors[i],
      colors[i + 1],
      colors[i + 2],
      colors[i + 3],
    ]);
    const stack: Array<any> = [[x, y]];
    while (stack.length > 0) {
      // const worker = new Worker(worker_setColor);
      const [x, y] = stack.pop();
      const { width, height } = canvas;
      const params = {
        x,
        y,
        size: { width, height },
        colors,
        repleceColor,
        targetColor,
        precision,
      };
      // worker.postMessage(params);
      // worker.onmessage = function (e) {
      //   console.log("e:", e.data);
      //   worker.terminate();
      // };
      const res = setColor(params);
      if (!res) continue;
      stack.push([x + 1, y], [x, y + 1], [x - 1, y], [x, y - 1]);
    }
    // ctx更新imageData
    ctx.putImageData(imageData, 0, 0);
    const newCanvas = getNewCanvas(ctx, imgPosition as IMGPosition);

    const base64 = newCanvas.toDataURL(`image/${format}`);
    newCanvas.remove();
    resolve(base64);
  });
};
export default repleceColor;
